import {InternalAxiosRequestConfig} from "axios"
import {genRandomStr, SimpleTypeConst, RandomStrTypeConst} from "st-common-core"
import {encryptAnyByTripleDes, encryptByRsaPubKey, TripleDesConst, DesTripleHeaderNameConst} from "st-common-encrypt"
import {getEnv} from "@env"
import {EnvNameEnum} from '@config'
import {ExcludeGenEncryptKeyUrlList, GenEncryptKeyUrlList, EncryptDataUrlList, ExcludeEncryptDataUrlList} from '@config'
import {useRsaStore} from "../stores/rsa-store.ts"
import {useDesStore} from "../stores/des-store.ts"

/**
 * 生成请求数据加密密钥的处理函数
 *
 * @param {InternalAxiosRequestConfig} config 请求配置对象
 * @returns {string | null} 返回生成的请求数据加密密钥，如果不需要生成加密密钥则返回 null
 */
export const genEncryptKeyHandler = (config: InternalAxiosRequestConfig): string | null => {
  /**
   * 判断是否需要生成加密密钥
   */
  // 如果在环境变量中配置关闭了对请求数据的加密
  if (!getEnv<boolean>(EnvNameEnum.REQ_DATA_IS_ENCRYPT, SimpleTypeConst.BOOL)) return null
  // 当前请求的 URL
  const url = config.url
  // 如果当前请求 URL 不需要生成加密密钥
  for (const excludeUrl of ExcludeGenEncryptKeyUrlList) {
    if (excludeUrl === '*' || url === excludeUrl || url.startsWith(excludeUrl)) return null
  }
  // 如果当前请求 URL 在需要生成加密密钥的请求 URL 列表中
  for (const urlNeedGen of GenEncryptKeyUrlList) {
    if (urlNeedGen === '*' || url === urlNeedGen || url.startsWith(urlNeedGen)) {
      /**
       * 生成加密密钥
       */
      // 随机生成密钥
      const key = genRandomStr(RandomStrTypeConst.ALL, TripleDesConst.KEY_LEN)
      // 加密密钥，并将加密后的密钥放入请求头中
      let keyEncrypted = encryptByRsaPubKey(key, useRsaStore().commonPubKey)
      config.headers[DesTripleHeaderNameConst.KEY] = keyEncrypted
      // 存储密钥
      // key 为加密后的密钥，value 为加密前的密钥
      useDesStore().saveKey(keyEncrypted, key)
      // 返回随机生成的密钥
      return key
    }
  }
}

/**
 * 加密请求数据处理函数
 *
 * @param {InternalAxiosRequestConfig} config 请求配置对象
 * @param {string | null} key 请求数据加密密钥
 */
export const encryptReqDataHandler = (config: InternalAxiosRequestConfig, key: string | null = null) => {
  /**
   * 判断是否需要加密请求数据
   */
  // 如果在环境变量中配置关闭了对请求数据的加密
  if (!getEnv<boolean>(EnvNameEnum.REQ_DATA_IS_ENCRYPT, SimpleTypeConst.BOOL)) return
  // 如果没有生成加密密钥
  if (!key) return
  // 当前请求的 URL
  const url = config.url
  // 如果当前请求 URL 不需要加密请求数据
  for (const excludeUrl of ExcludeEncryptDataUrlList) {
    if (excludeUrl === '*' || url === excludeUrl || url.startsWith(excludeUrl)) return
  }
  // 如果当前请求 URL 在需要加密请求数据的请求 URL 列表中
  for (const urlNeedEncrypt of EncryptDataUrlList) {
    if (urlNeedEncrypt === '*' || url === urlNeedEncrypt || url.startsWith(urlNeedEncrypt)) {
      /**
       * 请求数据加密处理
       */
      // GET 请求数据加密
      if (config.method === 'get') {
        config.params = encryptAnyByTripleDes({data: config.params, key})
      }
      // 其他请求方式数据加密
      else {
        config.data = encryptAnyByTripleDes({data: config.data, key})
      }
      // 在请求头中表明请求数据经过了加密
      config.headers[DesTripleHeaderNameConst.IS_DES_TRIPLE] = true
      return
    }
  }
}
